home *** CD-ROM | disk | FTP | other *** search
- unit E_MemMap;
- interface
- { This Unit implements an interface to Win32 memory mapped files. It
- can be used to map data simply residing in memory or data residing
- in a file. The data can be fully mapped into the processes address
- space or chunks can be mapped. It also provides capabilities for
- processes to synchronize via mutexes. When mapping sections of the
- memory, you must be aware that the Win32 memory mapped file interface
- requires that when you are requesting an offset into the memory
- region, this offset must be a multiple of the system's memory
- allocation granularity (I've called it PageSize). At this point
- it is 64K. This is not a concern when you are mapping anything less
- than 64K. However, to map anything > 64K the total memory size
- mapped must be a multiple of 64K or you will not have access to
- the memorysize MOD 64K bytes left over. Basically there are five
- rules to be successful when using these routines:
- 1. Mapname must be unique for each different case you use
- these objects (MyMap1 for case 1, MyMap2 for case 2
- etc.).However, each process using the same memory map
- MUST use the same MapName.
- 2. Call MapExisting before CreateMemMap or FCreateMemMap.
- If another process has already started the mapping,
- all you want to do is map to the existing map. ie.
- If NOT MapExisting then CreateMemMap.
- 3. If your processes are going to write to the mapped
- memory, it is suggested you use the mutex stuff.
- 4. Pay heed to the warning above concerning seeking
- offsets into the mapped memory. Whenever you call
- the seek function, always check for an error. Errors
- in mapping to the file will result in the Memmap
- pointer being Nil.
- 5. You MUST call LeaveCriticalSection after calling
- EnterCriticalSection or you will lock other processes wishing
- to use the map into an infinite wait state. Always use
- a Try..Finally block.
- }
- Uses
- Classes,Windows;
- Const
- hMemMap = $FFFFFFFF;
- Type
- //Map to memory
- TEMemMap = Class(TComponent)
- Private
- FhFile : THandle; //File handle, hMemMap when simple memory
- FhMap : THandle; //Mapping handle
- FMap : Pointer; //Memory Pointer
- FMapSize : Cardinal; //Mapping Page Size
- FMemSize : Cardinal; //Maximum size allocated, >=FileSize when a file
- FPageSize : Cardinal; //Minimum System allocation size
- FMaxSeeks : Cardinal; //Maximum seeks available,(FMemSize DIV PageSize)-1
- FMapError : Integer; //Error returned
- FhMutex : THandle; //Mutex handle for sharing
- FInMutex : Boolean; //Internal flag
- Function SetMapError : Boolean;
- Procedure SetMemSize(Size : Cardinal);
- Public
- Constructor Create(Aowner : TComponent); Override;
- Destructor Destroy; Override;
- //Create a mutex for sychronizing access
- Function CreateMutex(Const MutexName : String) : Boolean;
- //Use the mutex
- Procedure EnterCriticalSection;
- //Release the mutex
- Procedure LeaveCriticalSection;
- //Map to existing memory map
- Function MapExisting(Const MapName : String;
- Const MapSize : Cardinal) : Boolean;Virtual;
- //Create a new memory map
- Function CreateMemMap(Const MapName : String;
- Const MapSize : Cardinal;
- Const MapData ) : Boolean;Virtual;
- //seek to an offset in the memory map
- Function Seek(Const OffSet : Cardinal) : Boolean;
- //duh?
- Procedure RaiseMappingException;Virtual;
-
- Property MemMap : Pointer Read FMap; //The mapped memory
- Property MapError : Integer Read FMapError Write FMapError;
- Property MemSize : Cardinal Read FMemSize Write SetMemSize; //Memory size to allocate
- Property PageSize : Cardinal Read FPageSize; //system returned page size
- Property MaxSeeks : Cardinal Read FMaxSeeks; //maximum seeks allowed
- end;
- //map to a file
- TEFileMap = Class(TEMemMap)
- Public
- Function FCreateMemMap(Const Filename : String;
- Const MapName : String;
- Const MapSize : Cardinal) : Boolean;
-
- Function FlushFileView : Boolean;
- end;
- implementation
- Uses
- SysUtils;
- Type
- EMappingException = class(Exception);
- Constructor TEMemMap.Create(AOwner : TComponent);
- Var
- SysInfo : TSystemInfo;
- begin
- Inherited Create(AOwner);
- FhFile:=hMemMap;
- GetSystemInfo(SysInfo);
- FPageSize:=SysInfo.dwAllocationGranularity;
- end;
- Destructor TEMemmap.Destroy;
- begin
- LeaveCriticalSection;
- If FhMutex<>0 then
- CloseHandle(FhMutex);
- If FMap<>Nil then
- UnMapViewOfFile(FMap);
- If FHMap<>0 then
- CloseHandle(FHMap);
- Inherited Destroy;
- end;
- Function TEMemMap.CreateMutex(Const MutexName : String) : Boolean;
- begin
- If FhMutex=0 then
- FhMutex:=Windows.CreateMutex(Nil,False,PChar(MutexName));
- If FhMutex=0 then
- Result:=SetMapError
- else
- Result:=True;
- end;
- Procedure TEMemMap.EnterCriticalSection;
- begin
- If (NOT FInMutex) AND (FhMutex>0) then
- begin
- WaitForSingleObject(FhMutex,INFINITE);
- FInMutex:=True;
- end;
- end;
- Procedure TEMemMap.LeaveCriticalSection;
- begin
- If FInMutex AND (FhMutex>0) then
- begin
- ReleaseMutex(FhMutex);
- FInMutex:=False;
- end;
- end;
- Function TEMemMap.SetMapError : Boolean;
- begin
- FMapError:=GetLastError;
- Result:=False;
- end;
- Procedure TEMemMap.RaiseMappingException;
- Var
- TError : Integer;
- begin
- If FMapError<>0 then
- begin
- LeaveCriticalSection;
- TError:=FMapError;
- FMapError:=0;
- Raise EMappingException.Create('Memory Mapping Error #'+IntToStr(TError));
- end;
- end;
- Procedure TEMemMap.SetMemSize(Size : Cardinal);
- begin
- FMemSize:=Size;
- If FMemSize>PageSize then
- FMaxSeeks:=(FMemSize DIV PageSize)-1
- else
- FMaxSeeks:=0;
- end;
- //map to an existing memory map described by MapName
- Function TEMemMap.MapExisting(Const MapName : String;
- Const MapSize : Cardinal) : Boolean;
- begin
- FMapSize:=MapSize;
- FMap:=Nil;
- FhMap:=OpenFileMapping(FILE_MAP_WRITE,BOOL(True),PChar(MapName));
- If FhMap<>0 then
- begin
- FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,0,MapSize);
- If FMap=Nil then
- begin
- CloseHandle(FHMap);
- FHMap:=0;
- SetMapError;
- end;
- end;
- Result:=FMap<>Nil;
- end;
- //Create a new memory mapping
- Function TEMemMap.CreateMemMap(Const MapName : String;
- Const MapSize : Cardinal;
- Const MapData ) : Boolean;
- begin
- If FMemSize=0 then
- FMemSize:=MapSize;
- FhMap:=CreateFileMapping(FhFile,nil,PAGE_READWRITE,0,FMemSize,PChar(MapName));
- If FhMap<>0 then
- begin
- FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,0,MapSize);
- If FMap<>Nil then
- begin
- If fHFile=hMemMap then
- begin
- EnterCriticalSection;
- Try
- Move(MapData,FMap^,MapSize);
- Finally
- LeaveCriticalSection;
- end;
- end;
- Result:=True;
- end
- else
- Result:=SetMapError;
- end
- else
- Result:=SetMapError;
- end;
- //seek to a different position in map (0..MaxSeeks)
- Function TEMemMap.Seek(Const OffSet : Cardinal) : Boolean;
- begin
- Result:=True;
- If NOT UnMapViewOfFile(FMap) then
- Result:=SetMapError
- else
- begin
- FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,OffSet*PageSize,FMapSize);
- If FMap=Nil then
- Result:=SetMapError;
- end;
- end;
- //Create a file mapping
- Function TEFileMap.FCreateMemMap(Const Filename : String;
- Const MapName : String;
- Const MapSize : Cardinal) : Boolean;
- Var
- TInt : Cardinal;
- begin
- FHFile:=CreateFile(PChar(FileName),GENERIC_READ OR GENERIC_WRITE,
- FILE_SHARE_READ OR FILE_SHARE_WRITE,NIl,OPEN_EXISTING,
- FILE_FLAG_RANDOM_ACCESS,0);
- If FhFile<>0 then
- begin
- Try
- Result:=CreateMemMap(MapName,MapSize,TInt);
- Finally
- CloseHandle(FhFile);
- end;
- end
- else
- Result:=SetMapError;
- end;
-
- Function TEFileMap.FlushFileView : Boolean;
- begin
- EnterCriticalSection;
- Try
- Result:=FlushViewOfFile(FMap,FMapSize) OR SetMapError;
- Finally
- LeaveCriticalSection;
- end;
- end;
- end.
-